import type { ComponentInfo, ComponentResolver, SideEffectsInfo } from './types'
import {
	getPackageInfo,
	isPackageExists,
} from 'local-pkg'

export function kebabCase(key: string) {
	const result = key.replace(/([A-Z])/g, ' $1').trim()
	return result.split(' ').join('-').toLowerCase()
}

export async function getPkgVersion(pkgName: string, defaultVersion: string): Promise<string> {
	try {
		const isExist = isPackageExists(pkgName)
		if (isExist) {
			const pkg = await getPackageInfo(pkgName)
			return pkg?.version ?? defaultVersion
		}
		else {
			return defaultVersion
		}
	}
	catch (err) {
		console.error(err)
		return defaultVersion
	}
}

export interface HicorUiResolverOptions {
	/**
	 * import style css or sass with components
	 *
	 * @default 'css'
	 */
	importStyle?: boolean | 'css' | 'sass'

	/**
	 * specify hicor-ui version to load style
	 *
	 * @default installed version
	 */
	version?: string

	/**
	 * auto import for directives
	 *
	 * @default true
	 */
	directives?: boolean

	/**
	 * exclude component name, if match do not resolve the name
	 */
	exclude?: RegExp

	/**
	 * a list of component names that have no styles, so resolving their styles file should be prevented
	 */
	noStylesComponents?: string[]

	/**
	 * nightly version
	 */
	nightly?: boolean
}

type HicorUiResolverOptionsResolved = Required<Omit<HicorUiResolverOptions, 'exclude'>> &
	Pick<HicorUiResolverOptions, 'exclude'>

/**
 * @deprecated
 * @param partialName
 * @param options
 */
function getSideEffectsLegacy(
	partialName: string,
	options: HicorUiResolverOptionsResolved,
): SideEffectsInfo | undefined {
	const { importStyle } = options
	if (!importStyle)
		return

	if (importStyle === 'sass') {
		return [
			'hicor-ui/packages/theme-chalk/src/base.scss',
			`hicor-ui/packages/theme-chalk/src/${partialName}.scss`,
		]
	}
	else if (importStyle === true || importStyle === 'css') {
		return [
			'hicor-ui/lib/theme-chalk/base.css',
			`hicor-ui/lib/theme-chalk/hc-${partialName}.css`,
		]
	}
}

function getSideEffects(dirName: string, options: HicorUiResolverOptionsResolved): SideEffectsInfo | undefined {
	const { importStyle, nightly } = options
	const esComponentsFolder = nightly ? '@hicor-ui/nightly/es/components' : 'hicor-ui/es/components'

	if (importStyle === 'sass') {
		return [`${esComponentsFolder}/base/style/index`, `${esComponentsFolder}/${dirName}/style/index`]
	}
	else if (importStyle === true || importStyle === 'css') {
		return [`${esComponentsFolder}/base/style/css`, `${esComponentsFolder}/${dirName}/style/css`]
	}
}

function resolveComponent(name: string, options: HicorUiResolverOptionsResolved): ComponentInfo | undefined {
	if (options.exclude && name.match(options.exclude))
		return

	if (!name.match(/^Hc[A-Z]/))
		return

	if (name.match(/^HcIcon.+/)) {
		return {
			name: name.replace(/^HcIcon/, ''),
			from: '@hicor-ui/icons-vue',
		}
	}

	const partialName = kebabCase(name.slice(2))// HcTableColumn -> table-column
	const { nightly } = options

	return {
		name,
		from: `${nightly ? '@hicor-ui/nightly' : 'hicor-ui/es'}`,
		sideEffects: getSideEffects(partialName, options),
	}
}

function resolveDirective(name: string, options: HicorUiResolverOptionsResolved): ComponentInfo | undefined {
	if (!options.directives)
		return

	const directives: Record<string, { importName: string; styleName: string }> = {
		Loading: { importName: 'HcLoadingDirective', styleName: 'loading' },
		Popover: { importName: 'HcPopoverDirective', styleName: 'popover' },
		InfiniteScroll: { importName: 'HcInfiniteScroll', styleName: 'infinite-scroll' },
	}

	const directive = directives[name]
	if (!directive)
		return

	const { nightly } = options

	return {
		name: directive.importName,
		from: `${nightly ? '@hicor-ui/nightly' : 'hicor-ui/es'}`,
		sideEffects: getSideEffects(directive.styleName, options),
	}
}

const noStylesComponents = ['HcAutoResizer']

/**
 * Resolver for Hicor Ui
 *
 */
export function HicorUiResolver(
	options: HicorUiResolverOptions = {},
): ComponentResolver[] {
	let optionsResolved: HicorUiResolverOptionsResolved

	async function resolveOptions() {
		if (optionsResolved)
			return optionsResolved
		optionsResolved = {
			version: await getPkgVersion('hicor-ui', '2.2.2'),
			importStyle: 'css',
			directives: true,
			exclude: undefined,
			noStylesComponents: options.noStylesComponents || [],
			nightly: false,
			...options,
		}
		return optionsResolved
	}

	return [
		{
			type: 'component',
			resolve: async (name: string) => {
				const options = await resolveOptions()

				if ([...options.noStylesComponents, ...noStylesComponents].includes(name))
					return resolveComponent(name, { ...options, importStyle: false })
				else return resolveComponent(name, options)
			},
		},
		{
			type: 'directive',
			resolve: async (name: string) => {
				return resolveDirective(name, await resolveOptions())
			},
		},
	]
}
